#include "packet/packet.h"
#include "packet/http_request_packet.h"
#include "base/util_string.h"

//cmd packet
static const char const_http_enter_char = '\r';
static const char const_http_newline_char = '\n';
static const char  const_http_colon_char = ':';
static const char  const_http_space_char = ' ';
static const char const_http_enter_newline_str[] = { '\r', '\n' };
static const char* const const_http_type_key = "Content-Type";
static const char* const const_http_type_value = "application/json";
static const char* const const_http_length_key = "Content-Length";
static const size_t const_http_top_vect_length = 3;

namespace weilin {

	HttpRequestPacket::HttpRequestPacket() :
		m_consumer_status(HTTP_IDLE)
	{
		m_is_request = true;
		m_http_top.Reset();
		m_head.Reset();
	}
	HttpRequestPacket::~HttpRequestPacket()
	{
		m_head.Reset();
	}

	bool HttpRequestPacket::Tobuffer(string& outBuffStr)
	{
		return false;
	}
	bool HttpRequestPacket::parseHttpTop(const string& top_str)
	{
		vector<string> vect_splited;
		string str_delim = " ";
		CUtils::StrSplit(top_str, str_delim, vect_splited);
		if (vect_splited.size() != const_http_top_vect_length)
		{
			return false;
		}
		m_http_top.m_method = vect_splited[0];
		m_http_top.uri = vect_splited[1];
		m_http_top.version = vect_splited[2];
		m_cmd = m_http_top.uri;

		if (m_http_top.m_method != "POST" && m_http_top.m_method != "GET")
		{
			return false;
		}
		if (m_http_top.version.find("HTTP/1") == string::npos)
		{
			return false;
		}
		return true;
	}

	ConsumerRetStatus HttpRequestPacket::Consume(const char& input)
	{
		m_recv_str.push_back(input);
		switch (m_consumer_status)
		{
		case HTTP_IDLE:
		{
			if (input == const_http_enter_char)
			{
				
				if (parseHttpTop(m_http_top_str) == false)
				{
					return CONSUM_RET_FAIL;
				}
				m_consumer_status = HTTP_NEW_LINE_KEY_CHAR;
				return CONSUM_RET_CONTINUE;
			}
			m_http_top_str.push_back(input);
			return CONSUM_RET_CONTINUE;
		}
		case HTTP_NEW_LINE_KEY_CHAR:
		{
			if (input != const_http_newline_char)
			{
				return CONSUM_RET_FAIL;
			}
			m_consumer_status = HTTP_KEY;
			return CONSUM_RET_CONTINUE;
		}
		case HTTP_KEY:
		{
			if (input == const_http_colon_char)
			{
				m_consumer_status = HTTP_SPACE;
				return CONSUM_RET_CONTINUE;
			}
			if (input == const_http_enter_char)
			{
				m_consumer_status = HTTP_NEW_LINE_BODY_CHAR;
				return CONSUM_RET_CONTINUE;
			}
			m_head.key.push_back(input);
			return CONSUM_RET_CONTINUE;
		}
		case HTTP_SPACE:
		{
			if (input != const_http_space_char)
			{
				return CONSUM_RET_FAIL;
			}
			m_consumer_status = HTTP_VALUE;
			return CONSUM_RET_CONTINUE;
		}
		case HTTP_VALUE:
		{
			if (input == const_http_enter_char)
			{
				m_consumer_status = HTTP_NEW_LINE_HEAD_CHAR;
				//already has the key err
				if (m_head_map.find(m_head.key) != m_head_map.end())
				{
					return CONSUM_RET_FAIL;
				}
				m_head_map[m_head.key] = m_head.value;
				m_head.Reset();
				return CONSUM_RET_CONTINUE;
			}
			m_head.value.push_back(input);
			return CONSUM_RET_CONTINUE;
		}

		case HTTP_NEW_LINE_HEAD_CHAR:
		{
			if (input != const_http_newline_char)
			{
				return CONSUM_RET_FAIL;
			}
			m_consumer_status = HTTP_KEY;
			return CONSUM_RET_CONTINUE;
		}
		case HTTP_NEW_LINE_BODY_CHAR:
		{
			if (input != const_http_newline_char)
			{
				return CONSUM_RET_FAIL;
			}
			map<string, string>::iterator index_it = m_head_map.find(const_http_type_key);
			if (index_it == m_head_map.end())
			{
				return CONSUM_RET_FAIL;
			}
			if (index_it->second != const_http_type_value)
			{
				return CONSUM_RET_FAIL;
			}

			index_it = m_head_map.find(const_http_length_key);
			if (index_it == m_head_map.end())
			{
				return CONSUM_RET_FAIL;
			}
			m_remain_body_length = boost::lexical_cast<int>(index_it->second);
			if (m_remain_body_length <= 0)
			{
				return CONSUM_RET_FAIL;
			}

			m_consumer_status = HTTP_BODY;
			return CONSUM_RET_CONTINUE;
		}
		case HTTP_BODY:
		{
			m_body.push_back(input);
			m_remain_body_length--;
			if (m_remain_body_length == 0)
			{
				return CONSUM_RET_SUCCESS;
			}
			return CONSUM_RET_CONTINUE;
		}
		default:
		{
			return CONSUM_RET_FAIL;
		}
		}
	}
}

